# transformer/transformer_1.py (应用Pydantic)

import json
from openai import OpenAI
from pydantic import ValidationError

# 导入数据模型
from utils.unified_formats import UnifiedResume, UnifiedJD

from config.API import api

client = OpenAI(
    api_key=api,
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)


def prompt_for_unified_structure(raw_json: str, role: str = "resume") -> str:
    """
    构造统一结构化 JSON 的 prompt，供大模型调用。
    'skills' 字段现在是一个包含 'hard_skills' 和 'soft_skills' 的对象。
    
    :param raw_json: 原始结构化 JSON 字符串
    :param role: 来源类型，'resume' 或 'jd'
    :return: prompt 字符串
    """
    # --- 基础指令部分 ---
    base_prompt = (
        "你是一位资深的人力资源（HR）和数据分析专家，负责将不同来源的结构化数据（简历或职位描述）转换成统一标准的JSON格式。\n"
        "请根据以下提供的原始JSON数据，严格按照指定的标准结构和约束进行输出。\n\n"
        "通用约束：\n"
        "1. 所有字段必须出现，缺失可置空或使用合理的默认值。\n"
        "2. 输出内容必须是且仅是一个合法的JSON对象，不要附加任何说明、代码块标记（如```json）或格式符号。\n"
        "3. 请深入理解原始数据内容，并作出最合理的推断和转换。\n\n"
    )

    # 定义了更精确的skills结构体，用于在prompt中复用 ---
    skills_structure = (
        '  "skills": {                  // [对象] 技能对象\n'
        '    "hard_skills": [],         // [文本数组] 所有技术相关的能力、语言、工具\n'
        '    "soft_skills": []          // [文本数组] 沟通、协作、抗压、学习等软技能\n'
        '  },\n'
    )

    # --- 根据角色动态定义目标结构 ---
    if role == "jd":
        # 对于职位描述(JD)，我们要求模型额外分析各维度的重要性权重
        target_structure_prompt = (
            "请将职位描述转换为以下标准结构。请特别注意各字段的[格式约束]，尤其是 `skills` 字段必须是一个包含 `hard_skills` 和 `soft_skills` 的对象。\n"
            "另外，你需要分析该职位的核心要求，并给出 `dimension_weights` 字段，所有权重加起来必须等于100。\n"
            "{\n"
            f"{skills_structure}"
            '  "languages": [],             // [文本数组] 语言要求，如英语四级。\n'
            '  "education_level": "",       // [标准化类别] 必须从 ["博士", "硕士", "本科", "大专", "不限"] 中选择一个。默认为 "不限"。\n'
            '  "experience_years": 0,       // [整数] 必须提取为阿拉伯数字整数。例如 "五年" -> 5。如果未提及或无要求，则为0。\n'
            '  "other_tags": [],            // [文本数组] 其他加分项或特殊要求。\n'
            '  "dimension_weights": {       // [对象] 各维度的重要性权重（整数，总和为100）。\n'
            '    "hard_skills": 40,              // 代表 hard_skills 的重要性\n'
            '    "soft_skills": 15,         // 代表 soft_skills 的重要性\n'
            '    "experience_years": 30,\n'
            '    "education_level": 10,\n'
            '    "languages": 5,\n'
            '    "other_tags": 0\n'
            '  }\n'
            "}\n"
        )
    else:  # role == "resume"
        # 对于简历，我们只做信息提取，但同样应用严格的格式约束
        target_structure_prompt = (
            "请将简历内容转换为以下标准结构。请特别注意各字段的[格式约束]，尤其是 `skills` 字段必须是一个包含 `hard_skills` 和 `soft_skills` 的对象。\n"
            "{\n"
            f"{skills_structure}"
            '  "languages": [],             // [文本数组] 语言能力，如英语、中文、日语等。\n'
            '  "education_level": "",       // [标准化类别] 必须从 ["博士", "硕士", "本科", "大专", "不限"] 中选择一个，代表其最高学历。默认为 "不限"。\n'
            '  "experience_years": 0,       // [整数] 必须提取为阿拉伯数字整数，代表其总工作经验年限。如果无法判断，则为0。\n'
            '  "other_tags": []             // [文本数组] 候选人的其他重要标签，如远程办公、开源项目经历等。\n'
            "}\n"
        )
    
    # --- 组合最终的 Prompt ---
    final_prompt = (
        f"{base_prompt}"
        f"{target_structure_prompt}\n"
        f"以下是待处理的原始JSON数据（来源于'{role}'）：\n"
        f"```json\n{raw_json}\n```\n"
    )
    return final_prompt


def transform_via_ai(parsed_json: dict, role: str = "resume") -> dict:
    """
    通过调用大模型，将JSON转换为统一标准格式，并使用Pydantic进行验证和清洗。
    """
    raw_json_str = json.dumps(parsed_json, ensure_ascii=False, indent=2)
    prompt = prompt_for_unified_structure(raw_json_str, role)

    try:
        completion = client.chat.completions.create(
            model="qwen-plus",
            messages=[{"role": "system", "content": "你是一个高度精确的结构化信息归一化工具。"},
                      {"role": "user", "content": prompt}],
            temperature=0.0,
        )
        response_content = completion.choices[0].message.content.strip()
        
        # 清理Markdown标记
        if response_content.startswith("```json"):
            response_content = response_content[7:].strip()
        if response_content.endswith("```"):
            response_content = response_content[:-3].strip()
        
        # 将AI返回的字符串解析为Python字典
        raw_data = json.loads(response_content)

        # --- [核心改造] 使用Pydantic进行解析、验证和清洗 ---
        if role == "resume":
            # 将字典数据传入UnifiedResume模型
            model = UnifiedResume(**raw_data)
        else: # role == "jd"
            # 将字典数据传入UnifiedJD模型
            model = UnifiedJD(**raw_data)
            
        # 将验证和转换后的Pydantic模型实例，转回标准的Python字典
        # .model_dump() 是 Pydantic v2 的方法，如果是 v1 请用 .dict()
        return model.model_dump()

    except json.JSONDecodeError:
        print(f"{role} 转换时 JSON 解析失败，返回内容：\n{response_content}")
        return {"error": "Invalid JSON", "raw_output": response_content}
    except ValidationError as e:
        # Pydantic验证失败
        print(f"Pydantic数据验证失败 ({role})，AI返回的数据不符合预定义模型:\n{e}")
        return {"error": "Pydantic validation failed", "details": str(e), "raw_output": raw_data if 'raw_data' in locals() else response_content}
    except Exception as e:
        print(f"调用大模型或处理时发生未知失败: {str(e)}")
        return {"error": str(e)}